package com.xgk.boot.module.core.service.customer;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xgk.boot.framework.common.constant.ErrorCodeConstants;
import com.xgk.boot.framework.common.exception.util.ServiceExceptionUtil;
import com.xgk.boot.framework.common.pojo.PageResult;
import com.xgk.boot.framework.common.util.object.BeanUtils;
import com.xgk.boot.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.xgk.boot.framework.security.core.LoginUser;
import com.xgk.boot.framework.security.core.util.SecurityFrameworkUtils;
import com.xgk.boot.module.core.controller.admin.customer.vo.CustomerAddressReqVO;
import com.xgk.boot.module.core.controller.admin.customer.vo.CustomerAddressSaveVO;
import com.xgk.boot.module.core.controller.admin.customer.vo.CustomerReqVO;
import com.xgk.boot.module.core.dal.entity.customer.CustomerAddressDO;
import com.xgk.boot.module.core.dal.entity.customer.CustomerBalanceDO;
import com.xgk.boot.module.core.dal.entity.customer.CustomerDO;
import com.xgk.boot.module.core.dal.iservice.CustomerAddressService;
import com.xgk.boot.module.core.dal.iservice.CustomerBalanceService;
import com.xgk.boot.module.core.dal.mapper.customer.CustomerAddressMapper;
import com.xgk.boot.module.core.dal.mapper.customer.CustomerBalanceMapper;
import com.xgk.boot.module.core.dal.redis.RedisKeyConstants;
import com.xgk.boot.module.core.enums.permission.RoleCodeEnum;
import com.xgk.boot.module.core.service.permission.UserRoleServiceImpl;
import com.xgk.boot.module.core.service.user.AdminUserServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CustomerAddressServiceImpl extends ServiceImpl<CustomerAddressMapper, CustomerAddressDO> implements CustomerAddressService {


    @Resource
    private UserRoleServiceImpl userRoleService;
    @Resource
    private AdminUserServiceImpl adminUserService;
    @Resource
    private CustomerServiceImpl customerService;
    @Autowired
    private CustomerAddressServiceImpl self;

    public CustomerAddressDO createCustAddress(CustomerAddressSaveVO customerAddressSaveVO){
        CustomerAddressSaveVO custAddressVo = preCustAddressVoCheck(customerAddressSaveVO);
        CustomerAddressDO customerAddressDO = BeanUtils.toBean(custAddressVo, CustomerAddressDO.class);
        boolean save = this.save(customerAddressDO);

        return customerAddressDO;
    }

    @CacheEvict(value = RedisKeyConstants.CUSTOMER_ADDRESS,key="#id")
    public CustomerAddressDO updateCustAddress(Long id ,CustomerAddressSaveVO customerAddressSaveVO){
        CustomerAddressDO custAddressDO = preUpdateCustAddressVoCheck(id,customerAddressSaveVO);
//        CustomerAddressDO customerAddressDO = BeanUtils.toBean(custAddressVo, CustomerAddressDO.class);
//        BeanUtils.copyProperties(custVO,custById);
        boolean b = this.updateById(custAddressDO);
        return custAddressDO;
    }

    private CustomerAddressSaveVO preCustAddressVoCheck(CustomerAddressSaveVO custAddressVo){

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if(!userRoleService.isCurrentUserAdmin()){
            CustomerDO customerDO = customerService.getCustCacheByUserId(loginUser.getId());
            if(customerDO ==null){
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CUSTOMER_NOT_EXISTS);
            }
            custAddressVo.setCustomerId(customerDO.getId());
            custAddressVo.setCustomerCode(customerDO.getCustomerCode());
        }else {
            if(StrUtil.isBlank(custAddressVo.getCustomerCode())){
                custAddressVo.setCustomerCode(RoleCodeEnum.ADMIN.getCode());
            }
        }
        if(StrUtil.isBlank(custAddressVo.getSn())){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_EMPTY,"address code");
        }
        LambdaQueryWrapperX<CustomerAddressDO> eq = new LambdaQueryWrapperX<CustomerAddressDO>().eq(CustomerAddressDO::getSn, custAddressVo.getSn());
        CustomerAddressDO one = this.getOne(eq);
        if(one !=null){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_REPEAT,"address code");
        }
        return custAddressVo;
    }

    private CustomerAddressDO preUpdateCustAddressVoCheck(Long id,CustomerAddressSaveVO custAddressVo){
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();

        CustomerAddressDO customerAddressDO = self.selectByIdFromCache(id);
        if(customerAddressDO ==null){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_EXISTS,"address");
        }
        if(!custAddressVo.getSn().equals(customerAddressDO.getSn())){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_NO_CHANGE,"address code");
        }
        if(!userRoleService.isCurrentUserAdmin()){
            CustomerDO customerDO = customerService.getCustCacheByUserId(loginUser.getId());
            if(customerDO ==null){
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CUSTOMER_NOT_EXISTS);
            }
            if(StrUtil.isBlank(custAddressVo.getCustomerCode()) || custAddressVo.getCustomerId()==null){
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_INFO_EMPTY,"customerId and customerCode");
            }
            if(!custAddressVo.getCustomerId().equals(customerDO.getId())
                    || !custAddressVo.getCustomerCode().equals(customerDO.getCustomerCode())){
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CUSTOMER_ADDRESS_EDIT_OWN);
            }
        }else {
            if(StrUtil.isBlank(custAddressVo.getCustomerCode())){
                custAddressVo.setCustomerCode(RoleCodeEnum.ADMIN.getCode());
            }
        }
        BeanUtils.copyProperties(custAddressVo,customerAddressDO);
        return customerAddressDO;
    }


    @Cacheable(value = RedisKeyConstants.CUSTOMER_ADDRESS,key="#id", unless = "#result == null")
    public CustomerAddressDO selectByIdFromCache(Long id){
        CustomerAddressDO byId = this.getById(id);
        return byId;
    }

    @CacheEvict(value = RedisKeyConstants.CUSTOMER_ADDRESS,key="#id")
    public Boolean deleteAddress(Long id){
        CustomerAddressDO byId = this.getById(id);
        if(byId == null){
            return false;
        }

        if(!userRoleService.isCurrentUserAdmin()){
            LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
            CustomerDO customerDO = customerService.getCustCacheByUserId(loginUser.getId());
            if(!byId.getCustomerCode().equals(customerDO.getCustomerCode())){
                throw ServiceExceptionUtil.exception(ErrorCodeConstants.CUSTOMER_ADDRESS_EDIT_OWN);
            }
        }
        byId.setDeleted(true);
        return this.removeById(id);
    }


    public PageResult<CustomerAddressDO> pageCustomerAddress(CustomerAddressReqVO addressReqVO){
        LambdaQueryWrapperX<CustomerAddressDO> addressWrapperX = new LambdaQueryWrapperX<>();
        if(!userRoleService.isCurrentUserAdmin()){
            LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
            CustomerDO customerDO = customerService.getCustCacheByUserId(loginUser.getId());
            addressWrapperX.eq(CustomerAddressDO::getCustomerId,customerDO.getId());
        }
        addressWrapperX.likeIfPresent(CustomerAddressDO::getShipperName,addressReqVO.getShipperName())
                .likeIfPresent(CustomerAddressDO::getSn,addressReqVO.getSn())
                .likeIfPresent(CustomerAddressDO::getCustomerCode,addressReqVO.getCustomerCode())
                .likeIfPresent(CustomerAddressDO::getCountry,addressReqVO.getCountry())
                .likeIfPresent(CustomerAddressDO::getPostcode,addressReqVO.getPostcode())
                .likeIfPresent(CustomerAddressDO::getState,addressReqVO.getState())
                .likeIfPresent(CustomerAddressDO::getCity,addressReqVO.getCity())
                .likeIfPresent(CustomerAddressDO::getTelephone,addressReqVO.getTelephone());
        if(StrUtil.isNotBlank(addressReqVO.getStreetAddress1())){
            addressWrapperX.and(wrapper -> wrapper
                    .like(CustomerAddressDO::getStreetAddress1, addressReqVO.getStreetAddress1())
                    .or()
                    .like(CustomerAddressDO::getStreetAddress2, addressReqVO.getStreetAddress1()));
        }
//        addressWrapperX.eq(CustomerAddressDO::getDeleted,false);
        Page<CustomerAddressDO> page=new Page<>(addressReqVO.getCurrent(),addressReqVO.getPageSize());
        Page<CustomerAddressDO> pageRes = this.page(page, addressWrapperX);
        return new PageResult<>(pageRes.getRecords(), pageRes.getTotal(),addressReqVO.getCurrent(),addressReqVO.getPageSize());
    }



}
